package com.azzcs.gatewayservice.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @Author: wzg
 * @Date: 2021/2/23 下午8:59
 */
@Slf4j
@Order(0)
@Component
public class TokenGatewayFilter implements GatewayFilter {
    @Autowired
    private RedisTemplate redisTemplate;

    private static List<String> ignorePath = new ArrayList<>();
    static {
      ignorePath.add("/user-service/user/login");
      ignorePath.add("/user-service/register");
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        // 忽略 token 校验
        RequestPath path = request.getPath();
        String pathValue = path.value();
        for (String ignore : ignorePath) {
            if(pathValue.startsWith(ignore)){
                return chain.filter(exchange);
            }
        }
        // 验证token
        if(!checkToken(request)){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            String data = "UNAUTHORIZED";
            DataBuffer wrap = response.bufferFactory().wrap(data.getBytes());
            return response.writeWith(Mono.just(wrap));
        }

        return chain.filter(exchange);
    }

    private boolean checkToken(ServerHttpRequest request) {
        HttpHeaders headers = request.getHeaders();
        List<String> list = headers.get("token");
        if(CollectionUtils.isEmpty(list)){
            return false;
        }

        String token = list.get(0);

        Object o = redisTemplate.opsForValue().get(token);
        if(o == null){
            return false;
        }
        // 续约
        redisTemplate.expire(token,30, TimeUnit.MINUTES);
        return true;
    }

}
